#include<iostream>
#include<assert.h>
using namespace std;
namespace sakura
{
	template<class T>
	struct list_Node{
		list_Node(const T& val=T())
		{
			date = val;
		}
		T date;
		list_Node<T>* prve = nullptr;
		list_Node<T>* next = nullptr;
	};
	template <class T,class ref, class ptm>
	struct list_iterator
	{
		typedef list_Node<T> Node;
		typedef list_iterator<T, ref, ptm> self;
		Node* ptr;
		list_iterator(Node* num)
			:ptr(num)
		{}
		ref operator*()
		{
			return ptr->date;
		}
		ptm operator->()
		{
			return &ptr->date;
		}
		self& operator++()
		{
			ptr = ptr->next;
			return *this;
		}
		self& operator--()
		{
			ptr = ptr->prve;
			return *this;
		}
		self& operator++(int)
		{
			self tmp(ptr);
			ptr = ptr->next;
			return tmp;
		}
		self& operator--(int)
		{
			self tmp(ptr);
			ptr = ptr->prve;
			return tmp;
		}
		bool operator!=(const self& num)
		{
			return ptr != num.ptr;
		}
	};
	//template<class T>
	//struct list_iterator {
	//	typedef list_Node<T> Node;
	//	typedef list_iterator<T> self;
	//	Node* ptr;
	//	list_iterator(Node* num)
	//		:ptr(num)
	//	{}
	//	T& operator*()
	//	{
	//		return ptr->date;
	//	}
	//	T* operator->()
	//	{
	//		return &ptr->date;
	//	}
	//	self& operator++()
	//	{
	//		ptr = ptr->next;
	//		return *this;
	//	}
	//	self& operator--()
	//	{
	//		ptr = ptr->prve;
	//		return *this;
	//	}
	//	self& operator++(int)
	//	{
	//		self tmp(ptr);
	//		ptr = ptr->next;
	//		return tmp;
	//	}
	//	self& operator--(int)
	//	{
	//		self tmp(ptr);
	//		ptr = ptr->prve;
	//		return tmp;
	//	}
	//	bool operator!=(const self& num)
	//	{
	//		return ptr != num.ptr;
	//	}
	//};
	//template<class T>
	//struct const_list_iterator {
	//	/*typedef list_Node<T> Node;
	//	typedef const_list_iterator<T> self;*/

	//	Node* ptr;
	//	const_list_iterator(Node* num)
	//		:ptr(num)
	//	{}
	//	const T& operator*() 
	//	{
	//		return ptr->date;
	//	}
	//	const T* operator->()
	//	{
	//		return &ptr->date;
	//	}
	//	self& operator++()
	//	{
	//		ptr = ptr->next;
	//		return *this;
	//	}
	//	self& operator--()
	//	{
	//		ptr = ptr->prve;
	//		return *this;
	//	}
	//	self& operator++(int)
	//	{
	//		self tmp(ptr);
	//		ptr = ptr->next;
	//		return tmp;
	//	}
	//	self& operator--(int)
	//	{
	//		self tmp(ptr);
	//		ptr = ptr->prve;
	//		return tmp;
	//	}
	//	bool operator!=(const self& num)
	//	{
	//		return ptr != num.ptr;
	//	}
	//};
	template<class T>
	class list {
		typedef list_Node<T> Node;
	public:
		typedef list_iterator<T,T&,T*> iterator;
		typedef list_iterator<T,const T&,const T*> const_iterator;
		void empty_Init()
		{
			_sakura = new Node;
			size = 0;
			_sakura->next = _sakura;
			_sakura->prve = _sakura;
		}
		list(const list<T>& L)
		{
			empty_Init();
			for (auto ch : L)
			{
				push_back(ch);
			}
		}
		list()
		{
			empty_Init();
		}
		list<T>& operator=(list<T>& L)
		{
			swap(L);
		}
		void swap(list<T> L)
		{
			std::swap(_sakura, L._sakura);
			std::swap(size, size);
		}
		iterator begin()
		{
			return _sakura->next;
		}
		iterator end()
		{
			return _sakura;
		}
		const_iterator begin() const
		{
			return _sakura->next;
		}
		const_iterator end() const
		{
			return _sakura;
		}
		bool empty()
		{
			return size == 0;
		}
		void insert(iterator pos, T val = T())
		{
			Node* n3 = pos.ptr;
			Node* n1 = n3->prve;
			Node* n2 = new Node(val);
			//n1 n2 n3
			n2->next = n3;
			n2->prve = n1;
			n3->prve = n2;
			n1->next = n2;
			size++;
		}
		size_t getsize()
		{
			return size;
		}
		void push_back(const T& val)
		{
			//Node* ptr = _sakura->prve;
			////ptr num sakura 
			//Node* num = new Node(val);
			//num->next = _sakura;
			//num->prve = ptr;
			//ptr->next = num;
			//_sakura->prve = num;
			//size++;
			insert(end(), val);
		}
		iterator erase(iterator pos)
		{
			assert(size >= 0);
			assert(pos != end());
			Node* n3 = pos.ptr;
			Node* n1 = n3->prve;
			Node* n2 = n3->next;
			delete[]n3;
			//n1 n2
			n1->next = n2;
			n2->prve = n1;
			size--;
			return n2;
		}
		void pop_back()
		{
			erase(--end());
		}
		void clear()
		{
			auto it = begin();
			while (it != end())
			{
				it = erase(it);
			}
		}
		~list()
		{
			clear();
			delete _sakura;
			size = 0;
			_sakura = nullptr;
		}
	private:
		Node* _sakura;
		size_t size;
	};
	void print(list<int> L)
	{
		auto it = L.begin();
		while (it != L.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
	}
	template<class x>
	void printf_container(const x& v)
	{
		auto it = v.begin();
		while (it != v.end())
		{
			cout << *it << " ";
			it++;
		}
		cout << endl;
		for (auto ch : v)
		{
			cout << ch << " ";
		}
		cout << endl;
	}
	void test()
	{
		list<int> L;
		L.push_back(1);
		L.push_back(2);
		L.push_back(3);
		L.push_back(4);
		L.push_back(5);
		print(L);
		L.pop_back();
		printf_container(L);
	}
}
